/** @jsxImportSource @emotion/react */
import { jsx,css, SerializedStyles} from "@emotion/react";
import * as React from "react";
import  { forwardRef, useLayoutEffect, useRef, useState } from "react";
import {
    autoUpdate,
    size,
    useId,
    useDismiss,
    useFloating,
    useInteractions,
    useListNavigation,
    useRole,
    FloatingFocusManager,
    FloatingPortal
} from "@floating-ui/react";
import {BlurTriggerRefInput, InputSize} from "./Form";


/*参考 原装例子  https://codesandbox.io/s/fragrant-water-bsuirj?file=/src/App.tsx
* */
interface ItemProps {
    children: React.ReactNode;
    active: boolean;
    //手机需要 区分哪一个选项
    index: number;
}

const Item =({ children, active,index, ref, ...rest }:ItemProps & React.HTMLProps<HTMLDivElement>) => {
    const id = useId();
    return (
        <div
            ref={ref}
            role="option"
            id={id}
            aria-selected={active}
            {...rest}
            style={{
                background: active ? "lightblue" : index%2===0? "none" : "lavender",
                padding: 4,
                cursor: "default",
                ...rest.style
            }}
        >
            {children}
        </div>
    );
};

interface ComboBoxDatalistProps  extends React.InputHTMLAttributes<HTMLInputElement> {
    /** The size of the input element */
    inputSize?: InputSize;
    /** 控制是否满上宽度;
     *  需要在<input> 上 去控制大尺寸上限的width:  ，以及自适应屏幕大小后的 max-width: 缩小尺寸。
     * */
    fullWidth?: boolean;
    //已经知道的列表
    datalist?: any[];
    //底层input的 value?: string | ReadonlyArray<string> | number; 可重载类型定义，修改匹配为字符串
    //value?: string;
    //底层input的onChange,参数类型是event:不能直接利用
    onListChange: (value: string|number) => void;
    value?: string;
}

/*输入组合框： 原装例子 的 AutoComplete();
只能是文本内容 datalist；
旧版本用了Highlighter高亮。
* */
export function ComboBoxDatalist({
                                     autoComplete,
                                     autoFocus,
                                     inputSize = "md",
                                     fullWidth=true,
                                     datalist=[],
                                     style,
                                     placeholder,
                                     value,
                                     onListChange,
                                     ...other
                                 }: ComboBoxDatalistProps){
    const [open, setOpen] = useState(false);
    const [inputValue, setInputValue] = useState(value);
    const [activeIndex, setActiveIndex] = useState<number | null>(null);

    const listRef = useRef<Array<HTMLElement | null>>([]);

    const { x, y, refs, strategy, context } = useFloating<
        HTMLInputElement
        >({
        whileElementsMounted: autoUpdate,
        open,
        onOpenChange: setOpen,
        middleware: [
            size({
                apply({ rects, availableHeight, elements }) {
                    Object.assign(elements.floating.style, {
                        width: `${rects.reference.width}px`,
                        maxHeight: `${availableHeight}px`
                    });
                },
                padding: 10
            })
        ]
    });

    // useLayoutEffect(() => {
    //     // IMPORTANT: When the floating element first opens, this effect runs when
    //     // the styles have **not yet** been applied to the element. A rAF ensures
    //     // we wait until the position is ready, and also runs before paint.
    //     // https://floating-ui.com/docs/react-dom#effects
    //     requestAnimationFrame(() => {
    //         if (activeIndex != null) {
    //             listRef.current[activeIndex]?.scrollIntoView({ block: "nearest" });
    //         }
    //     });
    // }, [activeIndex]);

    const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(
        [
            useRole(context, { role: "listbox" }),
            useDismiss(context),
            useListNavigation(context, {
                listRef,
                activeIndex,
                onNavigate: setActiveIndex,
                virtual: true,
                loop: true
            })
        ]
    );

    function onChange(event: React.ChangeEvent<HTMLInputElement>) {
        const value = event.target.value;
        setInputValue(value);

        if (value) {
            setOpen(true);
            setActiveIndex(0);
        } else {
            setOpen(false);
        }
    }

    const items =inputValue? datalist.filter((item) =>
            item.toLowerCase().includes(inputValue.toLowerCase())
        )
     :
    datalist;       //全部可看

    return (
        <>
            <BlurTriggerRefInput
                onSave={function (text: string): void {
                    onListChange(text);
                }}
                {...getReferenceProps({
                    ref: refs.setReference,
                    onChange,
                    value: inputValue,
                    placeholder: placeholder,
                    "aria-autocomplete": "list",
                    onKeyDown(event) {
                        if (event.key === "Enter" &&
                            activeIndex != null &&
                            items[activeIndex]) {
                            setInputValue(items[activeIndex]);
                            setActiveIndex(null);
                            setOpen(false);
                        }
                    },
                    onPointerDown(event) {
                       setOpen(true);
                    },
                    style: {
                        ...style,
                    }
                })}

                {...other}
            />
            <FloatingPortal>
                {open && (
                    <FloatingFocusManager
                        context={context}
                        initialFocus={-1}
                        visuallyHiddenDismiss
                    >
                        <div
                            {...getFloatingProps({
                                ref: refs.setFloating,
                                style: {
                                    position: strategy,
                                    left: x ?? 0,
                                    top: y ?? 0,
                                    background: "#eee",
                                    color: "black",
                                    overflowY: "auto"
                                }
                            })}
                        >
                            {items.map((item, index) => (
                                <Item index={index}
                                    {...getItemProps({
                                        key: item,
                                        ref(node) {
                                            listRef.current[index] = node;
                                        },
                                        onClick() {
                                            setInputValue(item);
                                            setOpen(false);
                                            //refs.reference.current?.focus();
                                        },
                                        style: {
                                            listStyleType: 'none',
                                            padding: 0,
                                            margin: 0,
                                        },
                                    })}
                                    active={activeIndex === index}
                                >
                                    {item}
                                </Item>
                            ))}
                        </div>
                    </FloatingFocusManager>
                )}
            </FloatingPortal>
        </>
    );
}


